﻿using NLog;
using System;
using System.Linq;

namespace Drive.AlertSystem
{
    public class EventBuilder : IAlertEventBuilder
    {
        private LogLevel logLevel;




        private EventBuilder() { }

        /// <summary>
        /// 产品名称，比如智能分单
        /// </summary>
        string product { get; set; }
        /// <summary>
        /// 业务名称，比如IM分单
        /// </summary>
        string bizname { get; set; }
        /// <summary>
        /// 数据库对象
        /// </summary>
        string rectype { get; set; }
        /// <summary>
        /// 数据库对象key
        /// </summary>
        string reckey { get; set; }
        /// <summary>
        /// 业务路径 斜杠分割 比如“智能分单/IM分单”
        /// </summary>
        string bizpath { get; set; }

        /// <summary>
        /// 事件消息
        /// </summary>
        string message { get; set; }

        /// <summary>
        /// 错误类型，用于解释错误原因
        /// </summary>
        string errtype { get; set; }
        /// <summary>
        /// 预定义的错误码，大写字母下划线分割，ERR_字符开始
        /// </summary>
        string errcode { get; set; }
        /// <summary>
        /// errname的中文描述
        /// </summary>
        string errdesc { get; set; }

        string id { get; set; }

        string reqhead { get; set; }
        string reqbody { get; set; }
        string respbody { get; set; }

        int elapsed { get; set; }

        /// <summary>
        /// 比如 表名+表主键值
        /// </summary>
        /// <param name="objtype"></param>
        /// <param name="objkey"></param>
        /// <returns></returns>
        public IAlertEventBuilder SetRecord(string objtype, object objkey)
        {
            this.rectype = objtype;
            this.reckey = objkey?.ToString();
            return this;
        }

        public IAlertEventBuilder SetErrorType(string errtype)
        {
            this.errtype = errtype;
            return this;
        }

        /// <summary>
        /// 业务模块路径，比如 智能分单/CRM分单
        /// </summary>
        /// <param name="bizpath"></param>
        /// <returns></returns>
        public IAlertEventBuilder SetBizPath(string bizpath)
        {
            this.bizpath = bizpath;
            return this;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="errcode">比如 ERR_NO_USER_ONLINE</param>
        /// <param name="errdesc">比如“没有用户在线”</param>
        /// <param name="errtype">比如 分单失败</param>
        /// <returns></returns>
        public IAlertEventBuilder SetError(string errcode, string errdesc)
        {
            this.errcode = errcode;
            this.errdesc = errdesc;
            return this;
        }

        public IAlertEventBuilder SetLogLevel(LogLevel logLevel)
        {
            this.logLevel = logLevel;
            return this;
        }

        public IAlertEventBuilder SetRequest(string id, string reqHead, string reqBody)
        {
            this.id = id;
            this.reqhead = reqHead;
            this.reqbody = reqBody;
            return this;
        }

        public IAlertEventBuilder SetResponse(string respBody, int elapsed)
        {
            this.respbody = respBody;
            this.elapsed = elapsed;
            return this;
        }

        public static IAlertEventBuilder Create(string product, string bizname, string message)
        {
            return new EventBuilder
            {
                product = product,
                bizname = bizname,
                bizpath = $"{product}/{bizname}",
                message = message
            };
        }
        public LogEventInfo Build()
        {
            return Build(null);
        }
        public LogEventInfo Build(Exception exception)
        {
            var logEvent = new NLog.LogEventInfo();
            logEvent.Level = this.logLevel ?? LogLevel.Info;
            logEvent.Message = this.message;
            logEvent.Exception = exception;
            logEvent.Properties.Add("id", this.id);
            logEvent.Properties.Add("product", this.product);
            logEvent.Properties.Add("bizname", this.bizname);
            logEvent.Properties.Add("objtype", this.rectype);
            logEvent.Properties.Add("objkey", this.reckey);
            logEvent.Properties.Add("bizpath", this.bizpath);
            logEvent.Properties.Add("errtype", this.errtype);
            logEvent.Properties.Add("errcode", this.errcode);
            logEvent.Properties.Add("errdesc", this.errdesc);
            logEvent.Properties.Add("reqhead", this.reqhead);
            logEvent.Properties.Add("reqbody", this.reqbody);
            logEvent.Properties.Add("respbody", this.respbody);
            logEvent.Properties.Add("elapsed", this.elapsed);

            var content = string.Join("\r\n", logEvent.Properties.Select(x => x.Key + ": " + x.Value));
            logEvent.Properties.Add("content", content);
            return logEvent;
        }
    }
}
